/**
 * There are <a href="https://github.com/thinkgem/jeesite">JeeSite</a> code generation
 */
package com.chlitina.store.modules.base.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.FetchMode;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.chlitina.store.common.service.BaseService;
import com.chlitina.store.modules.base.dao.StoreProductDao;
import com.chlitina.store.modules.base.entity.StoreProduct;
import com.chlitina.store.modules.inventory.model.InventoryQuery;
import com.chlitina.store.modules.sys.entity.Store;
import com.chlitina.store.modules.sys.utils.StoreUtils;

/**
 * 店面产品Service
 * 
 * @author liujiang
 * @version 2013-09-26
 */
@Component
@Transactional(readOnly = true)
public class StoreProductService extends BaseService {

	@SuppressWarnings("unused")
	private static Logger logger = LoggerFactory
			.getLogger(StoreProductService.class);

	@Autowired
	private StoreProductDao storeProductDao;

	public StoreProduct get(Long id) {
		return storeProductDao.findOne(id);
	}

	@Transactional(readOnly = false)
	public void save(StoreProduct storeProduct) {
		storeProductDao.save(storeProduct);
	}

	@Transactional(readOnly = false)
	public StoreProduct getByProduct(long productId) {
		Store store = StoreUtils.getStore();
		DetachedCriteria dc = storeProductDao.createDetachedCriteria();
		dc.add(Restrictions.eq("store", store));
		dc.add(Restrictions.eq("product.id", productId));
		List<StoreProduct> find = storeProductDao.find(dc);
		if (find.size() > 0) {
			return find.get(0);
		} else {
			return null;
		}
	}

	@Transactional(readOnly = false)
	public List<StoreProduct> findByStore() {
		DetachedCriteria dc = storeProductDao.createDetachedCriteria();
		Store store = StoreUtils.getStore();
		dc.add(Restrictions.eq("store", store));
		dc.addOrder(Order.asc("id"));
		List<StoreProduct> storeProducts = storeProductDao.find(dc);
		List<StoreProduct> removeObjs = new ArrayList<StoreProduct>();
		List<Integer> validStoreProudctIDs = getValidStoreProudctIDs();
		for (StoreProduct storeProduct : storeProducts) {
			if(storeProduct.getProduct_type()==StoreProduct.TYPE_SELF){
				continue;
			}
			if (!contains(validStoreProudctIDs, storeProduct.getId().intValue())) {
				removeObjs.add(storeProduct);
			}
		}
		storeProducts.removeAll(removeObjs);
		return storeProducts;
	}

	boolean contains(List<Integer> ids, int value) {
		for (Integer integer : ids) {
			if (integer.intValue() == value) {
				return true;
			}
		}
		return false;
	}

	@Transactional(readOnly = false)
	public List<StoreProduct> findByStatus(int type, int productType) {
		Store store = StoreUtils.getStore();
		DetachedCriteria dc = storeProductDao.createDetachedCriteria();
		dc.add(Restrictions.eq("store", store));
		dc.add(Restrictions.eq("product_type", type));
		dc.addOrder(Order.asc("id"));
		List<StoreProduct> storeProducts = storeProductDao.find(dc);
		List<StoreProduct> removeObjs = new ArrayList<StoreProduct>();
		if (type == StoreProduct.TYPE_SYS) {
			List<Integer> validStoreProudctIDs = getValidStoreProudctIDs();
			for (StoreProduct storeProduct : storeProducts) {
				if (!contains(validStoreProudctIDs, storeProduct.getId()
						.intValue())) {
					removeObjs.add(storeProduct);
					continue;
				}
				//-1 is all type
				if (productType != -1 && storeProduct.getProduct().getProductCategory().getType() != productType) {
					removeObjs.add(storeProduct);
				}
			}
			storeProducts.removeAll(removeObjs);
		}
		return storeProducts;
	}

	public List<Integer> getValidStoreProudctIDs() {
		String sql = "SELECT DISTINCT SP.ID AS STORE_PRODUCT_ID FROM store_product SP, PRODUCT P , PRODUCT_CATEGORY_STORE_TYPE PCST  , STORE S WHERE  SP.CT_PRODUCT_ID= P.ID  AND P.CATEGORY_ID = PCST.PRODUCT_CATEGORY_ID   AND PCST.STORE_TYPE_ID = S.STORE_TYPE   AND S.ID ="
				+ StoreUtils.getStore().getId().longValue() + ";";
		SQLQuery createSQLQuery = storeProductDao.getSession().createSQLQuery(
				sql);
		return createSQLQuery.list();
	}

	private DetachedCriteria findStoreSelfProduct(Store store,
			String productname) {
		DetachedCriteria dc = storeProductDao.createDetachedCriteria();
		dc.add(Restrictions.eq("store", store));
		dc.addOrder(Order.asc("id"));
		dc.add(Restrictions.eq("product_type", 1));
		dc.setFetchMode("storeSelfProduct", FetchMode.JOIN);
		dc.createAlias("storeSelfProduct", "storeSelfProduct");
		dc.add(Restrictions.like("storeSelfProduct.name", productname,
				MatchMode.ANYWHERE));
		return dc;
	}

	@Transactional(readOnly = false)
	public List<StoreProduct> findStoreselfProducts() {
		return findByStatus(StoreProduct.TYPE_SELF, -1);
	}

	@Transactional(readOnly = false)
	public InventoryQuery findStoreProducts(InventoryQuery inventoryQuery) {
		Store store = StoreUtils.getStore();
		String productName = inventoryQuery.getProductName();
		inventoryQuery.getStoreProducts().clear();
		if (productName != null && !productName.isEmpty()) {
			DetachedCriteria dc = storeProductDao.createDetachedCriteria();
			dc.add(Restrictions.eq("store", store));
			dc.addOrder(Order.asc("id"));
			dc.add(Restrictions.eq("product_type", 0));
			dc.setFetchMode("product", FetchMode.JOIN);
			dc.createAlias("product", "product");
			dc.add(Restrictions.like("product.name", productName,
					MatchMode.ANYWHERE));
			int amount = 1;
			if (inventoryQuery.isIncludingZero()) {
				amount = 0;
			}
			dc.add(Restrictions.ge("amount", amount));// greater than or equal
			List<StoreProduct> find = storeProductDao.find(dc);
			inventoryQuery.getStoreProducts().addAll(find);
			find = storeProductDao
					.find(findStoreSelfProduct(store, productName));
			inventoryQuery.getStoreProducts().addAll(find);

		} else {
			DetachedCriteria dc = storeProductDao.createDetachedCriteria();
			dc.add(Restrictions.eq("store", store));
			int amount = 1;
			if (inventoryQuery.isIncludingZero()) {
				amount = 0;
			}
			dc.add(Restrictions.ge("amount", amount));// greater than or equal
			dc.addOrder(Order.asc("id"));
			List<StoreProduct> find = storeProductDao.find(dc);
			inventoryQuery.getStoreProducts().addAll(find);
		}
		return inventoryQuery;
	}
}
